﻿using System;
using MFilesAPI;

namespace FSAG.UserImporter
{
    /// <summary>
    /// Contains the State of a user object
    /// </summary>
    public enum State
    {
        /// <summary>
        /// User marked as activ can log in to the system
        /// </summary>
        Activ,

        /// <summary>
        /// Deactiv users are still stored on the server but the user can't log in
        /// </summary>
        Deactiv,

        /// <summary>
        /// User marked as deleted will be deleted on the server
        /// </summary>
        Deleted
    }

    /// <summary>
    /// Represent the user with all related attributes and implicit converters for creating a loginaccount or a useraccount
    /// </summary>
    public class User
    {
        /// <summary>
        /// The unique ID of the current user
        /// </summary>
        public int AccountID { get; set; }

        /// <summary>
        /// Contains a timestamp of the time when the user entity was modified
        /// </summary>
        public string Modified { get; set; }

        /// <summary>
        /// The username of the current user
        /// </summary>
        public string UserName { get; set; }

        /// <summary>
        /// The password of the current user
        /// </summary>
        public string MFilesPassword { get; set; }

        /// <summary>
        /// The firstname of the current user
        /// </summary>
        public string FirstName { get; set; }

        /// <summary>
        /// The lastname of the current user
        /// </summary>
        public string LastName { get; set; }

        /// <summary>
        /// The fullname of the current user (concatenated by the firstname and lastname)
        /// </summary>
        public string FullName { get; set; }

        /// <summary>
        /// The mail adress of the current user
        /// </summary>
        public string Mail { get; set; }

        /// <summary>
        /// The state (active, deactiv, deleted) of the current user
        /// </summary>
        public State State { get; set; }

        /// <summary>
        /// The type of license for the current user (read-only, concurrent, named, none)
        /// </summary>
        public MFLicenseType LicenseType { get; set; }

        /// <summary>
        /// True, if the current user is active
        /// </summary>
        public bool Enabled { get { return State == State.Activ;} }

        /// <summary>
        /// The ServerRole of the current user
        /// </summary>
        public MFLoginServerRole ServerRole { get; set; }

        /// <summary>
        /// Permission for changing the metadata structure
        /// </summary>
        public MFUserAccountVaultRole MFUserAccountVaultRoleChangeMetadataStructure { get; set; }

        /// <summary>
        /// Permission for creating objects
        /// </summary>
        public MFUserAccountVaultRole MFUserAccountVaultRoleCreateObjects { get; set; }

        /// <summary>
        /// Permission for changing the object security settings
        /// </summary>
        public MFUserAccountVaultRole MFUserAccountVaultRoleChangeObjectSecurity { get; set; }

        /// <summary>
        /// Permission for destroying objects irrevocable
        /// </summary>
        public MFUserAccountVaultRole MFUserAccountVaultRoleDestroyObjects { get; set; }

        /// <summary>
        /// Permission for forcing undo checkout
        /// </summary>
        public MFUserAccountVaultRole MFUserAccountVaultRoleForceUndoCheckout { get; set; }

        /// <summary>
        /// Permission for full control 
        /// </summary>
        public MFUserAccountVaultRole MFUserAccountVaultRoleFullControl { get; set; }

        /// <summary>
        /// Permission for setting internal user
        /// </summary>
        public MFUserAccountVaultRole MFUserAccountVaultRoleInternalUser { get { return MFUserAccountVaultRole.MFUserAccountVaultRoleInternalUser; } }

        /// <summary>
        /// Permission for managing common views
        /// </summary>
        public MFUserAccountVaultRole MFUserAccountVaultRoleManageCommonViews { get; set; }

        /// <summary>
        /// Permission for managing traditional folders
        /// </summary>
        public MFUserAccountVaultRole MFUserAccountVaultRoleManageTraditionalFolders { get; set; }

        /// <summary>
        /// Permission for managing user accounts
        /// </summary>
        public MFUserAccountVaultRole MFUserAccountVaultRoleManageUserAccounts { get; set; }

        /// <summary>
        /// Permission for seeing all objects
        /// </summary>
        public MFUserAccountVaultRole MFUserAccountVaultRoleSeeAllObjects { get; set; }

        /// <summary>
        /// Permission for undeleting objects
        /// </summary>
        public MFUserAccountVaultRole MFUserAccountVaultRoleUndeleteObjects { get; set; }

        /// <summary>
        /// Dependent on the state, if active the role is set to vaultRoleLogIn
        /// </summary>
        public MFUserAccountVaultRole MFUserAccountVaultRoleLogIn
        {
            get
            {
                return State == State.Activ ? MFUserAccountVaultRole.MFUserAccountVaultRoleLogIn : MFUserAccountVaultRole.MFUserAccountVaultRoleNone;
            }
        }

        /// <summary>
        /// The language of the current user
        /// </summary>
        public short Language { get; set; }

        /// <summary>
        /// The first assigned group to the current user
        /// </summary>
        public string UserGroup1 { get; set; }

        /// <summary>
        /// The second assigned group to the current user
        /// </summary>
        public string UserGroup2 { get; set; }

        /// <summary>
        /// The third assigned group to the current user
        /// </summary>
        public string UserGroup3 { get; set; }

        /// <summary>
        /// List of all set permissions 
        /// </summary>
        public MFUserAccountVaultRole VaultRoles { get; set; }

        /// <summary>
        /// Checks wheter the user was modified
        /// </summary>
        /// <returns>Returns true, if a modified timestamp is set</returns>
        public bool IsModified()
        {
            return !String.IsNullOrWhiteSpace(Modified);
        }

        /// <summary>
        /// Checks wheter this user was deleted
        /// </summary>
        /// <returns>Returns true, if the user is deleted</returns>
        public bool IsDeleted()
        {
            return (AccountID != 0 && State == State.Deleted);
        }

        /// <summary>
        /// Checks wheter this user was irrevocabledeleted
        /// </summary>
        /// <returns>Returns true, if the firstname and lastname are empty</returns>
        public bool IsIrrevocableDeleted()
        {
            return (string.IsNullOrEmpty(FirstName) && string.IsNullOrEmpty(LastName));
        }

        /// <summary>
        /// Checks wheter this user has assigned groups
        /// </summary>
        /// <returns>Returns true, if the current user has assigned groups</returns>
        public bool HasAssignedGroups()
        {
            return !string.IsNullOrEmpty(UserGroup1) || !string.IsNullOrEmpty(UserGroup2) ||
                   !string.IsNullOrEmpty(UserGroup3);
        }

        /// <summary>
        /// Method used to implicitly convert a given user to a userAccount
        /// </summary>
        /// <param name="account">The user instance which should be converted</param>
        /// <returns>Returns the converted user account</returns>
        public static implicit operator UserAccountClass(User account)
        {
            return new UserAccountClass
                       {
                           ID = account.AccountID,
                           InternalUser = true,
                           LoginName = account.UserName,
                           VaultLanguage = account.Language,
                           VaultRoles =
                               account.MFUserAccountVaultRoleChangeMetadataStructure |
                               account.MFUserAccountVaultRoleCreateObjects |
                               account.MFUserAccountVaultRoleChangeObjectSecurity |
                               account.MFUserAccountVaultRoleForceUndoCheckout |
                               account.MFUserAccountVaultRoleDestroyObjects |
                               account.MFUserAccountVaultRoleFullControl |
                               account.MFUserAccountVaultRoleInternalUser |
                               account.MFUserAccountVaultRoleManageCommonViews |
                               account.MFUserAccountVaultRoleManageTraditionalFolders |
                               account.MFUserAccountVaultRoleManageUserAccounts |
                               account.MFUserAccountVaultRoleSeeAllObjects |
                               account.MFUserAccountVaultRoleUndeleteObjects |
                               account.MFUserAccountVaultRoleLogIn
                       };
        }

        /// <summary>
        /// Method used to implicitly convert a given user to a LoginAccount
        /// </summary>
        /// <param name="account">The user instance which should be converted </param>
        /// <returns>Returns the converted user account</returns>
        public static implicit operator LoginAccountClass(User account)
        {
            return new LoginAccountClass
                       {
                AccountType = MFLoginAccountType.MFLoginAccountTypeMFiles,
                EmailAddress = account.Mail,
                Enabled = account.Enabled,
                FullName = account.FullName,
                LicenseType = account.LicenseType,
                ServerRoles = MFLoginServerRole.MFLoginServerRoleNone,
                UserName = account.UserName
            };
        }

        /// <summary>
        /// Checks wheter a given object is equals to this object
        /// </summary>
        /// <param name="obj"></param>
        /// <returns>True, if the object is equals</returns>
        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }

            return UserName.Equals(((User)obj).UserName);
        }

        /// <summary>
        /// Returns the hascode of this object
        /// </summary>
        /// <returns>Returns the hashcode</returns>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

    }
}